<template>
    <ElForm ref="formInstance" :model="formData" :rules="formRules" :label-width="props.labelWidth" :label-position="props.labelPosition" :size="props.size" class="my-form">
        <template v-for="group in props.formItemList">
            <div v-if="group.list" class="form-group">
                <div v-if="group.name" class="form-group-name">{{ group.name }}</div>
                <ElRow :gutter="group.layout?.rowGutter">
                    <ElCol v-for="item in group.list" :span="item.extends?.span || group.layout?.span || 24">
                        <MyFormItem v-model="formData[item.prop]" v-bind="item"> </MyFormItem>
                    </ElCol>
                </ElRow>
            </div>
            <MyFormItem v-else v-model="formData[group.prop]" v-bind="group"> </MyFormItem>
        </template>
    </ElForm>
</template>

<script setup lang="ts">
import * as formRule from './rules';
import type { FormDefineProps, IFormInstance } from './props';
import { type FormInstance } from 'element-plus';
const props = withDefaults(defineProps<FormDefineProps>(), {
    labelPosition: 'left',
    labelWidth: '100px',
    size: 'default',
    formData() {
        return {};
    },
    formItemList() {
        return [];
    },
    formRules() {
        return {};
    },
});

const formInstance = ref<FormInstance>();
const formData = reactive<any>({});

onBeforeMount(() => {
    setData(props.formData);
});

const validate = async (): Promise<boolean> => {
    const result = await formInstance.value?.validate().catch(() => {});
    return result || false;
};

const clearValidate = () => {
    formInstance.value?.clearValidate();
};

const setData = (data: any) => {
    for (let prop in data) {
        formData[prop] = data[prop];
    }
};

const getData = () => {
    return { ...formData };
};

const clearData = () => {
    setData(props.formData);
};

const formRules = computed(() => {
    const rules: any = {};
    for (let prop in props.formRules) {
        rules[prop] = formRule.transformFileRule(props.formRules[prop]);
    }
    return rules;
});

defineExpose<IFormInstance<any>>({
    validate,
    clearValidate,
    setData,
    getData,
    clearData,
});
</script>

<style scoped>
.form-group {
    border: 1px solid var(--el-border-color-light);
    position: relative;
    padding: 24px 24px 6px;
    border-radius: 8px;
    margin-bottom: 24px;
}
.form-group-name {
    line-height: 32px;
    padding: 0px 12px;
    position: absolute;
    top: -16px;
    background-color: var(--el-bg-color);
    font-size: 16px;
}
</style>
